﻿namespace Dissemination.MVC.MVCContrib.CallHandlers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using UnityContrib.Interfaces;
    using Microsoft.Practices.Unity.InterceptionExtension;
    using Microsoft.Practices.Unity;
    using UnityContrib.Types;
    using MVCContrib.Interfaces;

    public class ControllerCallHandler : Microsoft.Practices.Unity.InterceptionExtension.ICallHandler
    {
        /// <summary>
        /// Gets or sets the logger.
        /// </summary>
        /// <value>The logger.</value>
        [Dependency]
        public ILoggerFacade Logger { get; set; }

        [Dependency]
        public IUnityContainer Container { get; set; }

        /// <summary>
        /// Implement this method to execute your handler processing.
        /// </summary>
        /// <param name="input">Inputs to the current call to the target.</param>
        /// <param name="getNext">Delegate to execute to get the next delegate in the handler
        /// chain.</param>
        /// <returns>Return value from the target.</returns>
        public IMethodReturn Invoke(IMethodInvocation input, Microsoft.Practices.Unity.InterceptionExtension.GetNextHandlerDelegate getNext)
        {
            IMethodReturn msg;
            try
            {
                Logger.Log(string.Format("BEFORE::ControllerCallHandler.Invoke for {0}",
                    input.Target.GetType().Name), 
                    Category.Debug, Priority.None);

                msg = getNext()(input, getNext);

                // If the controller is being handled by MVCContrib - implements IControllerBase
                // then we'll set the Container.  Attempts to do a BuildUp here do not work as
                // expected so the Container Setter is expected to perform a Container.Buildup(this)
                // See Base\ControllerBase Container setter for details
                if (msg.ReturnValue is IControllerBase)
                    ((IControllerBase)msg.ReturnValue).Container = Container;

                Logger.Log(string.Format("AFTER::ControllerCallHandler.Invoke for {0}",
                    input.Target.GetType().Name),
                    Category.Debug, Priority.None);
            
            }
            catch (Exception ex)
            {
                msg = input.CreateExceptionMethodReturn(ex);
            }

            return msg;
        }

        /// <summary>
        /// Order in which the handler will be executed
        /// </summary>
        /// <value></value>
        public int Order { get; set; }

    }
}
